import { isFunc, notNilEmpty } from 'qx-util';
import {
  IPSAppCounterRef,
  IPSAppDataEntity,
  IPSAppDEUILogic,
  IPSAppView,
  IPSControl,
  IPSControlContainer,
  IPSDBPortletPart,
  IPSDEDEActionLogic,
  IPSDEUIActionLogic,
  IPSDEUIDEActionLogic,
  IPSUIAction,
} from '../../../exports';
import { IPSModelObject } from '../../../ipsmodel-object';
import { LogUtil } from '../log-util/log-util';

/**
 * 格式化请求json路径
 *
 * @author chitanda
 * @date 2021-04-13 14:04:24
 * @export
 * @param {string} path
 * @return {*}  {string}
 */
export function formatPath(path: string): string {
  // 合成路径，需要判断模型路径是否从 PSSYSAPPS 开始
  if (path?.indexOf('PSSYSAPPS/') === 0) {
    //合成路径
    const pos = path.indexOf('/');
    return path.substring(path.indexOf('/', pos + 1));
  }
  return path;
}

/**
 * 根据方法标识，获取对象。一层层向上取
 *
 * @author chitanda
 * @date 2021-04-16 14:04:32
 * @export
 * @param {IPSModelObject} modelObject
 * @param {string} funcTag
 * @return {*}  {(IPSModelObject | IPSModelObject[])}
 */
export function getByFunc(
  modelObject: IPSModelObject,
  funcTag: string,
): IPSModelObject | IPSModelObject[] {
  if (!modelObject) {
    LogUtil.warn('父对象无效，查找方法: ', funcTag);
    return;
  }
  if (isFunc(modelObject[funcTag])) {
    return modelObject[funcTag]();
  }
  const t = modelObject.getParentPSModelObject();
  if (t) {
    return getByFunc(t, funcTag);
  }
}

/**
 * 标识模糊匹配
 *
 * @author chitanda
 * @date 2021-04-13 14:04:16
 * @param {IPSModelObject} obj
 * @param {string} tag
 * @param {boolean} [ignoreCase]
 * @return {*}  {boolean}
 */
export function testPSModel(
  obj: IPSModelObject,
  tag: string,
  ignoreCase?: boolean,
): boolean {
  if (notNilEmpty(tag)) {
    if (ignoreCase === true) {
      tag = tag.toUpperCase();
      if (
        obj.modelFilePath?.toUpperCase() === tag ||
        obj.id?.toUpperCase() === tag ||
        obj.codeName?.toUpperCase() === tag ||
        obj.name?.toUpperCase() === tag
      ) {
        return true;
      }
      return false;
    } else {
      return (
        obj.modelFilePath === tag ||
        obj.id === tag ||
        obj.codeName === tag ||
        obj.name === tag
      );
    }
  }
  return false;
}

/**
 * 模糊查询部件：根据视图查询 + 标识查部件
 *
 * @author chitanda
 * @date 2021-04-13 14:04:02
 * @export
 * @param {IPSAppView | IPSControlContainer | IPSDBPortletPart} view 视图
 * @param {string} tag 标识（可以为：「modelFilePath、id、codeName、name」）
 * @param {boolean} [ignoreCase] 忽略大小写
 * @return {*}  {IPSControl}
 */
export function getControl(
  view: IPSAppView | IPSControlContainer | IPSDBPortletPart,
  tag: string,
  ignoreCase?: boolean,
): IPSControl {
  if (view && view.getPSControls) {
    return view
      .getPSControls()
      ?.find(item => testPSModel(item, tag, ignoreCase));
  }
}

/**
 * 从模型组中查找
 *
 * @author chitanda
 * @date 2021-04-13 14:04:01
 * @export
 * @template T
 * @param {T[]} modelObjArr 模型组
 * @param {string} tag 标识（可以为：「modelFilePath、id、codeName、name」）
 * @param {boolean} [ignoreCase]
 * @return {*}  {T} 返回值可声明为具体类型
 */
export function getByModelObjectArr<T extends IPSModelObject = IPSModelObject>(
  modelObjArr: T[],
  tag: string,
  ignoreCase?: boolean,
): T {
  return modelObjArr?.find(item => testPSModel(item, tag, ignoreCase));
}

/**
 * 获取指定模型对象，第一层级的getPSUIAction模型对象实例。
 *
 * @author chitanda
 * @date 2021-04-22 11:04:31
 * @export
 * @param {IPSModelObject} modelObject
 * @return {*}  {Promise<IPSUIAction>}
 */
export async function getPSUIActionByModelObject(
  modelObject: IPSModelObject,
  tag?: string,
): Promise<IPSUIAction> {
  if (modelObject) {
    const s = modelObject.getPSModelService();
    const actionModel =
      modelObject.M.getPSUIAction ||
      modelObject.M.getNextPSUIAction ||
      modelObject.M.getDstPSAppDEUIAction;
    if (actionModel && actionModel.modelref === true) {
      let entity: IPSAppDataEntity;
      const entityModel =
        tag === ''
          ? modelObject.M.getDstPSAppDataEntity
          : actionModel.getPSAppDataEntity;
      if (entityModel) {
        if (entityModel.modelref === true) {
          entity = await s.getPSAppDataEntity(entityModel.path);
        } else {
          entity = await s.getPSAppDataEntity(entityModel);
        }
        if (entity) {
          await entity.fill();
          const deUIAction = entity.findPSAppDEUIAction(actionModel.id);
          if (deUIAction) {
            return deUIAction;
          }
        }
      }
      const uiAction = s.getPSUIAction(actionModel.id);
      if (uiAction) {
        return uiAction as IPSUIAction;
      }
    }
  }
  return null;
}

/**
 * 获取指定模型对象中的实体界面逻辑
 *
 * @author chitanda
 * @date 2021-07-07 21:07:05
 * @export
 * @param {IPSModelObject} modelObject
 * @return {*}  {Promise<IPSAppDEUILogic>}
 */
export async function getPSAppDEUILogicByModelObject(
  modelObject: IPSModelObject,
): Promise<IPSAppDEUILogic> {
  if (modelObject) {
    const s = modelObject.getPSModelService();
    const uiLogic = modelObject.M.getPSAppDEUILogic;
    if (uiLogic && uiLogic.modelref === true) {
      let entity: IPSAppDataEntity;
      const entityModel = modelObject.M.getPSAppDataEntity;
      if (entityModel.modelref === true) {
        entity = await s.getPSAppDataEntity(entityModel.path);
      } else {
        entity = await s.getPSAppDataEntity(entityModel);
      }
      if (entity) {
        return entity.findPSAppDEUILogic(uiLogic.id);
      }
    }
  }
  return null;
}

/**
 * 获取实体行为逻辑中的Dst实体行为
 *
 * @author chitanda
 * @date 2021-07-09 11:07:56
 * @export
 * @param {(IPSDEUIDEActionLogic | IPSDEDEActionLogic)} modelObject
 * @return {*}
 */
export async function getDstPSAppDEAction(
  modelObject: IPSDEUIDEActionLogic | IPSDEDEActionLogic,
) {
  if (modelObject) {
    const action = modelObject.M.getDstPSAppDEAction;
    if (action && action.modelref === true) {
      const entity = modelObject.getDstPSAppDataEntity();
      await entity.fill(true);
      return entity.findPSAppDEAction(action.id);
    }
  }
  return null;
}

/**
 * 获取实体行为界面逻辑中的Dst实体行为
 *
 * @author chitanda
 * @date 2021-07-09 10:07:05
 * @export
 * @param {IPSDEUIActionLogic} modelObject
 * @return {*}
 */
export async function getDstPSAppDEUIAction(modelObject: IPSDEUIActionLogic) {
  if (modelObject) {
    const action = modelObject.M.getDstPSAppDEUIAction;
    if (action && action.modelref === true) {
      const entity = modelObject.getDstPSAppDataEntity();
      await entity.fill(true);
      return entity.findPSAppDEUIAction(action.id);
    }
  }
  return null;
}

/**
 * 在指定模型上查找AppDataEntity
 *
 * @author chitanda
 * @date 2021-05-15 12:05:12
 * @export
 * @param {IPSModelObject} relatedPSModelObject
 * @return {*}  {IPSAppDataEntity}
 */
export function findRelatedPSAppDataEntity(
  relatedPSModelObject: IPSModelObject,
): IPSAppDataEntity {
  return (
    (getByFunc(
      relatedPSModelObject,
      'getPSAppDataEntity',
    ) as IPSAppDataEntity) ||
    (this.getParentPSModelObject(
      relatedPSModelObject,
      'app.dataentity.IPSAppDataEntity',
    ) as IPSAppDataEntity)
  );
}

/**
 * 递归去父的 control.IPSControlContainer 上查找计数器，直到找到最上层
 *
 * @author chitanda
 * @date 2022-10-26 16:10:19
 * @export
 * @param {IPSModelObject} relatedPSModelObject
 * @param {*} obj
 * @return {*}  {(IPSAppCounterRef | null)}
 */
export function findPSAppCounterRefByParent(
  relatedPSModelObject: IPSModelObject,
  obj: any,
): IPSAppCounterRef | null {
  const container = relatedPSModelObject.getParentPSModelObject(
    'control.IPSControlContainer',
  ) as IPSControlContainer;
  if (container) {
    const ref = container.findPSAppCounterRef(obj);
    if (ref) {
      return ref;
    }
    return findPSAppCounterRefByParent(container.getParentPSModelObject(), obj);
  }
  return null;
}
